package com.bobo.netty.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class DateTimeUtils {
    private static final Logger logger = LoggerFactory.getLogger(DateTimeUtils.class.getSimpleName());

    public final static DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    public final static DateFormat DATE_FORMAT2 = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
    public final static DateFormat DATE_FORMAT3 = new SimpleDateFormat("MMM dd", Locale.US);
    public final static DateFormat DATE_FORMAT4 = new SimpleDateFormat("MM-dd", Locale.getDefault());
    public final static DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm", Locale.getDefault());
    public final static DateFormat TIME_FORMAT2 = new SimpleDateFormat("hh:mma", Locale.US);
    public final static DateFormat TIME_FORMAT3 = new SimpleDateFormat("MM-dd HH:mm", Locale.getDefault());
    public final static DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
    public final static DateFormat DATETIME_FORMAT2 = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
    public final static DateFormat DATETIME_FORMAT3 = new SimpleDateFormat("MMM dd, hh:mma", Locale.US);
    public final static DateFormat DATETIME_FORMAT4 = new SimpleDateFormat("EEEE, MMM dd, hh:mma", Locale.US);
    public final static DateFormat DATETIME_FORMAT5 = new SimpleDateFormat("HH:mm", Locale.getDefault());
    public final static DateFormat DATETIME_FORMAT6 = new SimpleDateFormat("MMddHHmm", Locale.getDefault());
    public final static DateFormat DATETIME_FORMAT7 = new SimpleDateFormat("yyyyMMddHHmm", Locale.getDefault());
    public static final String FORMAT_YEAR_MONTH_DEFAULT = "yyyyMM";
    public static final String FORMAT_YEAR_MONTH_DAY_DEFAULT = "yyyy-MM-dd";
    public static final FastDateFormat FORMAT_YYYYMMDDHHMMSS = FastDateFormat.getInstance("yyyyMMddHHmmss");

    public static final FastDateFormat FORMAT_MMDDHHMMSS = FastDateFormat.getInstance("MMddHHmmss");

    public static final FastDateFormat FORMAT_YMDHMS = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");

    public static final FastDateFormat FORMAT_YYYYMMDD = FastDateFormat.getInstance("yyyyMMdd");

    public static final FastDateFormat FORMAT_YYYY_MM_DD = FastDateFormat.getInstance("yyyy-MM-dd");


    /**
     * 超过时间是否按照id查询UA
     *
     * @return boolean
     * @Author:ALong (ZengWeiLong)
     * @date 2016年5月12日
     */
    public static boolean isSearchById() {
        Integer ctime = Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        return ctime > 20160420;
    }

    public static Date parse(String string, DateFormat format) {
        Date date = null;

        SimpleDateFormat sdf = getSimpleDateFormat(format);

        try {
            if (StringUtils.isEmpty(string)) {
                return null;
            }
            date = sdf.parse(string);
        } catch (ParseException e) {
            if (format.equals(DATE_FORMAT) || format.equals(DATE_FORMAT2)) {
                logger.error("Error when parsing date from string: " + string);
            } else if (format.equals(TIME_FORMAT)) {
                logger.error("Error when parsing time from string: " + string);
            } else if (format.equals(DATETIME_FORMAT) || format.equals(DATETIME_FORMAT2) || format.equals(DATETIME_FORMAT3)) {
                logger.error("Error when parsing datetime from string: " + string);
            }
        }

        return date;
    }

    private static SimpleDateFormat getSimpleDateFormat(DateFormat format) {
        SimpleDateFormat sdf = null;
        if (DATE_FORMAT.equals(format)) {
            sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
        } else if (DATE_FORMAT2.equals(format)) {
            sdf = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
        } else if (DATE_FORMAT3.equals(format)) {
            sdf = new SimpleDateFormat("MMM dd", Locale.US);
        } else if (DATE_FORMAT4.equals(format)) {
            sdf = new SimpleDateFormat("MM-dd", Locale.getDefault());
        } else if (TIME_FORMAT.equals(format)) {
            sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
        } else if (TIME_FORMAT2.equals(format)) {
            sdf = new SimpleDateFormat("hh:mma", Locale.US);
        } else if (TIME_FORMAT3.equals(format)) {
            sdf = new SimpleDateFormat("MM-dd HH:mm", Locale.getDefault());
        } else if (DATETIME_FORMAT.equals(format)) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
        } else if (DATETIME_FORMAT2.equals(format)) {
            sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault());
        } else if (DATETIME_FORMAT3.equals(format)) {
            sdf = new SimpleDateFormat("MMM dd, hh:mma", Locale.US);
        } else if (DATETIME_FORMAT4.equals(format)) {
            sdf = new SimpleDateFormat("EEEE, MMM dd, hh:mma", Locale.US);
        } else if (DATETIME_FORMAT5.equals(format)) {
            sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
        } else if (DATETIME_FORMAT6.equals(format)) {
            sdf = new SimpleDateFormat("MMddHHmm", Locale.getDefault());
        } else if (DATETIME_FORMAT7.equals(format)) {
            sdf = new SimpleDateFormat("yyyyMMddHHmm", Locale.getDefault());

        }
        return sdf;
    }

    public static String format(Date date, String pattern) {
        return format(date, pattern, null);
    }

    public static String format(Date date, String pattern, Locale locale) {
        String dateStr = "";

        if (locale == null) {
            locale = Locale.getDefault();
        }
        if (StringUtils.isBlank(pattern)) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        if (date != null) {
            DateFormat format = new SimpleDateFormat(pattern, locale);
            dateStr = format.format(date);
        }
        return dateStr;
    }

    public static String format(Date date, DateFormat format) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = getSimpleDateFormat(format);
        return sdf.format(date);
    }

    public static String format(Date date, DateFormat format, TimeZone tz) {
        SimpleDateFormat sdf = getSimpleDateFormat(format);
        if (format != null && tz != null) {
            sdf.setTimeZone(tz);
        }
        return (date == null ? null : sdf.format(date));
    }

    public static Date getNthMinutesLater(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, n);
        return calendar.getTime();
    }

    public static Date getNthMinutesLater(Date date, int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, n);
        return calendar.getTime();
    }

    public static Date getBeginningOfThisMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getBeginningOfNextMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getBeginningOfNextNextMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 2);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getBeginningOfTheDay() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getNthHourLater(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR_OF_DAY, n);
        return calendar.getTime();
    }

    public static Date getTomorrow() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getTheBeginOfNthDaysBefore(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -n);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getTheEndOfNthDaysBefore(int n) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -n);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    public static Date getTomorrow(int interval) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, interval);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getToday(int interval) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, interval);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getToday() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getPrevMinutes(int offset) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, -offset);
        return calendar.getTime();
    }

    public static Date getYesterday(int interval) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        calendar.set(Calendar.HOUR_OF_DAY, interval);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getTheDayAfterTomorrow() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 2);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getNextDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, 1);
        return cal.getTime();
    }

    public static Date getNextMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, 1);
        return cal.getTime();
    }

    public static Date getDateByOffset(int dayOffset, int minuteOffset) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, dayOffset);
        calendar.add(Calendar.MINUTE, minuteOffset);
        return calendar.getTime();
    }

    public static Date getDateByOffset(int dayOffset, int hourOffset, int minuteOffset) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, dayOffset);
        calendar.add(Calendar.HOUR, hourOffset);
        calendar.add(Calendar.MINUTE, minuteOffset);
        return calendar.getTime();
    }

    public static Boolean isBetween(Date date, Date start, Date end) {
        return date.compareTo(start) == 1 && date.compareTo(end) == -1;
    }

    /**
     * 调日期整天数、分钟
     *
     * @param date
     * @param dayOffset
     * @param minuteOffset
     * @return
     */
    public static Date getDateByOffset(Date date, int dayOffset, int minuteOffset) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if (dayOffset != 0) {
            calendar.add(Calendar.DATE, dayOffset);
        }
        if (minuteOffset != 0) {
            calendar.add(Calendar.MINUTE, minuteOffset);
        }
        return calendar.getTime();
    }

    public static Date getDateByOffset(Date date, int monthOffset, int dayOffset, int minuteOffset) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if (dayOffset != 0) {
            calendar.add(Calendar.DATE, dayOffset);
        }
        if (minuteOffset != 0) {
            calendar.add(Calendar.MINUTE, minuteOffset);
        }
        if (monthOffset != 0) {
            calendar.add(Calendar.MONTH, monthOffset);
        }
        return calendar.getTime();
    }

    public static Date getNextNthMonday(int n) {
        Calendar calendar = Calendar.getInstance();
        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calendar.add(Calendar.WEEK_OF_YEAR, -1);
        }
        calendar.add(Calendar.WEEK_OF_YEAR, n);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getLastMonday() {
        Calendar calendar = Calendar.getInstance();

        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calendar.add(Calendar.WEEK_OF_YEAR, -1);
        }
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.add(Calendar.DATE, -7);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getThisMonday() {
        Calendar calendar = Calendar.getInstance();

        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calendar.add(Calendar.WEEK_OF_YEAR, -1);
        }
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static int getDayCountOfMonth(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public static Date getNextMonday() {
        Calendar calendar = Calendar.getInstance();

        if (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
            calendar.add(Calendar.WEEK_OF_YEAR, 1);
        }
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getNextNextMonday() {
        Calendar calendar = Calendar.getInstance();

        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calendar.add(Calendar.WEEK_OF_YEAR, 1);
        } else {
            calendar.add(Calendar.WEEK_OF_YEAR, 2);
        }
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Boolean isSameWeek(Date dateOne, Date dateTwo) {
        Calendar calOne = Calendar.getInstance();
        calOne.setTime(dateOne);
        Calendar calTwo = Calendar.getInstance();
        calTwo.setTime(dateTwo);
        //判断是否是周日，如果是，则其周再-1
        if (calOne.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calOne.add(Calendar.DATE, -1);
        }
        if (calTwo.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calTwo.add(Calendar.DATE, -1);
        }
        if (calOne.get(Calendar.YEAR) == calTwo.get(Calendar.YEAR) &&
                calOne.get(Calendar.WEEK_OF_YEAR) == calTwo.get(Calendar.WEEK_OF_YEAR)) {
            return true;
        }
        int subYear = calOne.get(Calendar.WEEK_OF_YEAR) - calTwo.get(Calendar.WEEK_OF_YEAR);
        if (subYear == 1 && calTwo.get(Calendar.MONTH) == 11) {
            if (calOne.get(Calendar.WEEK_OF_YEAR) == calTwo.get(Calendar.WEEK_OF_YEAR)) {
                return true;
            }
        } else if (subYear == -1 && calOne.get(Calendar.MONTH) == 11) {
            if (calOne.get(Calendar.WEEK_OF_YEAR) == calTwo.get(Calendar.WEEK_OF_YEAR)) {
                return true;
            }
        }
        return false;
    }

    public static Date getBeginningOfTheDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getTheDayAfterYesterday() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -2);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getOffsetDay(int offsetDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, offsetDay);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getYearOffset(Date date, int offset) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, offset);
        return calendar.getTime();
    }

    public static int getCurrentMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    public static int getCurrentYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.YEAR);
    }

    public static int getLeftDaysOfThisMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH) - calendar.get(Calendar.DAY_OF_MONTH) + 1;
    }

    public static int getDaysOfThisMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DAY_OF_MONTH);
    }


    /**
     * @param month 格式 yyyyMM
     * @return 时间戳 Timestamp
     * @throws ParseException
     */
    public static Date getMonthTime(int month) throws ParseException {
        String dateStr = String.valueOf(month);
        Date date = null;
        if (StringUtils.isNotBlank(dateStr)) {
            SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_YEAR_MONTH_DEFAULT);
            try {
                date = dateFormat.parse(dateStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        return date;
    }

    /**
     * @return month 格式 yyyyMM
     * @throws ParseException
     */
    public static int getNowMonthTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_YEAR_MONTH_DEFAULT);
        Date date = new Date();
        String month = dateFormat.format(date);
        return Integer.valueOf(month);
    }

    /**
     * @param date 时间
     * @return month 格式 yyyyMM
     * @throws ParseException
     */
    public static int getMonthTime(Date date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_YEAR_MONTH_DEFAULT);
        String month = dateFormat.format(date);
        return Integer.valueOf(month);
    }

    /**
     * @return month 格式 yyyyMM
     * @throws ParseException
     */
    public static int getPreMonthTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_YEAR_MONTH_DEFAULT);
        String month = dateFormat.format(calendar.getTime());
        return Integer.valueOf(month);
    }

    public static Date getFirstSecondOfDay(Date date) {
        return DateUtils.truncate(date, Calendar.DATE);
    }

    public static Date getLastSecondOfDay(Date date) {
        return DateUtils.addSeconds(
                DateUtils.addDays(DateUtils.truncate(date, Calendar.DATE), 1),
                -1);
    }

    public static Date getTheDayCurrentMonth(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DATE, day);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getTheDayLastMonth(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -1);
        calendar.set(Calendar.DATE, day);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getTheFirstDayMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Boolean isAfterOtherDayCurrentMonth(Integer day) {
        if (day == null) {
            return false;
        }
        Date startDate = getTheDayCurrentMonth(day);
        Date endDate = getBeginningOfNextMonth();
        Date now = new Date();
        return !startDate.after(now) && endDate.after(now);
    }

    /**
     * 根据生日计算年龄
     *
     * @param birthday
     * @return
     * @throws ParseException
     */
    public static Integer getAgeByBirthday(Date birthday) {
        Calendar cal = Calendar.getInstance();
        if (birthday == null) {
            return null;
        }
        if (cal.before(birthday)) {
            return null;
        }
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH) + 1;
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birthday);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH) + 1;
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        int age = yearNow - yearBirth;
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }

    public static boolean isWithinXHours(final Date date, int x) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.HOUR_OF_DAY, x);
        if (date.before(now.getTime())) {
            return true;
        }
        return false;
    }

    public static Date addHours(Date date, int x) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR_OF_DAY, x);
        return cal.getTime();
    }

    public static boolean isNotWithInTheDay(Date time) {
        return !(time.after(DateTimeUtils.getBeginningOfTheDay()) && time.before(DateTimeUtils.getTomorrow()));
    }

    public static Date getEndOfYesterday() {
        Calendar endOfTodayCalendar = Calendar.getInstance();
        endOfTodayCalendar.add(Calendar.DATE, -1);
        endOfTodayCalendar.set(Calendar.HOUR_OF_DAY, 23);
        endOfTodayCalendar.set(Calendar.MINUTE, 59);
        endOfTodayCalendar.set(Calendar.SECOND, 59);
        endOfTodayCalendar.set(Calendar.MILLISECOND, 0);
        return endOfTodayCalendar.getTime();
    }

    public static Date getTimeOfDate(Date date, int hour, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, minute);
        cal.set(Calendar.SECOND, second);
        return cal.getTime();
    }

    /**
     * 计算两个时间相差的月份数据
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int getMonthsOfDate(Date date1, Date date2) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        String date1Str = format(date1, "yyyy-MM");
        String date2Str = format(date2, "yyyy-MM");
        Calendar bef = Calendar.getInstance();
        Calendar aft = Calendar.getInstance();
        try {
            bef.setTime(sdf.parse(date1Str));
            aft.setTime(sdf.parse(date2Str));
        } catch (ParseException e) {
            logger.error("计算两个时间相差的月份数据 异常！", e);
            return 0;
        }
        int result = aft.get(Calendar.MONTH) - bef.get(Calendar.MONTH);
        int month = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR)) * 12;
        System.out.println(Math.abs(month + result));
        return Math.abs(month + result);
    }

    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(String s) {
        if (StringUtils.isBlank(s)) {
            logger.error("时间为空！");
            return null;
        }
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = new Long(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }

    /**
     * 输出yyyyMMddHHmmss格式的日期字符串
     *
     * @param date
     * @return
     */
    public static String formatYYYYMMDDHHMMSS(Date date) {
        if (date == null) {
            return "";
        }
        return FORMAT_YYYYMMDDHHMMSS.format(date);
    }

    /**
     * 输出MMddHHmmss格式的日期字符串
     *
     * @param date
     * @return
     */
    public static String formatMMDDHHMMSS(Date date) {
        if (date == null) {
            return "";
        }
        return FORMAT_MMDDHHMMSS.format(date);
    }

    /**
     * 输出格式为yyyy-MM-dd HH:mm:ss的日期字符串
     *
     * @param date
     * @return
     */
    public static String formatYMDHMS(Date date) {
        if (date == null) {
            return "";
        }
        return FORMAT_YMDHMS.format(date);
    }

    /**
     * 输出格式为yyyyMMdd的日期字符串
     *
     * @param date
     * @return
     */
    public static String formatYYYYMMDD(Date date) {
        if (date == null) {
            return "";
        }
        return FORMAT_YYYYMMDD.format(date);
    }

    /**
     * 输出格式为yyyy-MM-dd的日期字符串
     *
     * @param date
     * @return
     */
    public static String formatYYYY_MM_DD(Date date) {
        if (date == null) {
            return "";
        }
        return FORMAT_YYYY_MM_DD.format(date);
    }


    /**
     * 计算播放时长，返回 HH:mm:ss
     *
     * @param seconds time in seconds.
     * @return time string in HH:mm:ss format.
     */
    public static String formatHHMMSS(long seconds) {
        return formatHHMMSS(seconds, false);
    }

    /**
     * 计算播放时长，返回 HH:mm:ss
     *
     * @param seconds time in seconds.
     * @return time string in HH:mm:ss format.
     */
    public static String formatHHMMSS(long seconds, boolean trimPrefix) {
        StringBuilder result = new StringBuilder();
        long[] time = new long[3];
        time[0] = seconds / 3600; // 时
        time[1] = (seconds % 3600) / 60; // 分
        time[2] = (seconds % 3600) % 60; // 秒
        boolean end = false;
        for (int i = 0; i < 3; i++) {
            long v = time[i];
            if (v == 0 && trimPrefix && !end) {
                continue;
            }
            end = true;
            if (v < 10) {
                result.append("0");
            }
            result.append(v);
            if (i == 2) {
                return result.toString();
            }
            result.append(":");
        }
        return result.toString();
    }

    public static int daysBetween(Long smdate, Long bdate) {
        long between_days = (bdate - smdate) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    public static int daysBetween(Date smdate, Date bdate) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            smdate = sdf.parse(sdf.format(smdate));
            bdate = sdf.parse(sdf.format(bdate));
            Calendar cal = Calendar.getInstance();
            cal.setTime(smdate);
            long time1 = cal.getTimeInMillis();
            cal.setTime(bdate);
            long time2 = cal.getTimeInMillis();
            long between_days = (time2 - time1) / (1000 * 3600 * 24);
            return Integer.parseInt(String.valueOf(between_days));
        } catch (ParseException e) {
            return 0;
        }

    }

    public static Date getDayStartTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getDayEndTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    //获取当前时间之前或之后某天的时间
    public static Date getFirstDate(Date d, int dayCount) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.add(Calendar.DAY_OF_YEAR, -dayCount);
        return calendar.getTime();
    }

    public static Date getPastYear(Date d, int yearCount) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.add(Calendar.YEAR, -yearCount);
        return calendar.getTime();
    }

    //本年第一天
    public static Date getFirstDayOfYear(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.set(calendar.get(Calendar.YEAR), 0, 1, 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    //本年最后一天的23点59分
    public static Date getLastDayOfYear(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
        }
        calendar.set(calendar.get(Calendar.YEAR), 11, 31, 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    //当月第一天的零点零分
    public static Date getThisMonthFirstDayStartTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date sdate = calendar.getTime();
        return sdate;
    }

    //本月月最后一天的23点59分
    public static Date getThisMonthLastDayEndTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.MONTH, 1);
        calendar.add(Calendar.MILLISECOND, -1);
        Date edate = calendar.getTime();
        return edate;
    }


}
